package com.yiyihealth.cherriesadmin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.Week;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.yiyihealth.cherriesadmin.core.http.HttpResult;
import com.yiyihealth.cherriesadmin.core.service.impl.BaseServiceImpl;
import com.yiyihealth.cherriesadmin.mapper.*;
import com.yiyihealth.cherriesadmin.model.*;
import com.yiyihealth.cherriesadmin.model.wrapper.OrdSchedulingTemplateWrapper;
import com.yiyihealth.cherriesadmin.service.OrdSchedulingTemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * 排版模板(OrdSchedulingTemplate)表服务实现类
 *
 * @author chen
 * @since 2020-09-14 20:03:29
 */
@Transactional
@Service("ordSchedulingTemplateService")
public class OrdSchedulingTemplateServiceImpl extends BaseServiceImpl<OrdSchedulingTemplate, OrdSchedulingTemplateWrapper, Long> implements OrdSchedulingTemplateService {
    @Resource
    private OrdSchedulingTemplateMapper ordSchedulingTemplateMapper;
    @Resource
    private OrdSchedulingMapper ordSchedulingMapper;
    @Resource
    private OrdSourceDetailMapper ordSourceDetailMapper;
    @Resource
    private PubBindInfoMapper bindInfoMapper;
    @Resource
    private PubHospitalMapper hospitalMapper;
    private Integer count = 0;

    @Resource
    private RedisTemplate<Object, Object> redisCacheTemplate;
    @Resource
    private OutRegPlanMapper outRegPlanMapper;


    @Autowired
    private void setEntityMapper() {
        super.setEntityMapper(ordSchedulingTemplateMapper);
    }

    @Override
    public OrdSchedulingTemplate insert(OrdSchedulingTemplate record) throws Exception {
        if (!Optional.ofNullable(record.getDepName()).isPresent()) {
            String redisKey = "departments:" + record.getHospitalId() + ":" + record.getDepId();
            if (redisCacheTemplate.hasKey(redisKey)) {
                PubDepartments departments = (PubDepartments) redisCacheTemplate.opsForValue().get(redisKey);
                record.setDepName(departments.getDepName());
            }
        }
        if (!Optional.ofNullable(record.getBinName()).isPresent()) {
            PubBindInfo bindInfo = bindInfoMapper.selectByPrimaryKey(record.getBinId());
            record.setBinName(bindInfo.getBinName());
        }
        if (!Optional.ofNullable(record.getDoctorName()).isPresent()) {
            String redisKey = "doctor:" + record.getHospitalId() + ":" + record.getDoctorId();
            if (redisCacheTemplate.hasKey(redisKey)) {
                PubDoctor doctor = (PubDoctor) redisCacheTemplate.opsForValue().get(redisKey);
                record.setDoctorName(doctor.getDoctorName());
            }
        }
        if (!Optional.ofNullable(record.getStatus()).isPresent()) {
            record.setStatus("0");
        }
        return super.insert(record);
    }

    /**
     * 根据模板生成每周排班
     *
     * @param record
     * @return
     * @throws Exception
     */
    @Override
    public synchronized String createScheduling(OrdSchedulingTemplate record, LocalDate visiteDate) throws Exception {
        count = 0;
        if (!Optional.ofNullable(visiteDate).isPresent()) {
            visiteDate = getVisiteDate(record);
        }
        String result = "";
        for (int i = 0; i <= record.getComingWeeks(); i++) {
            LocalDate tempDate = visiteDate.plusWeeks(i);
            long num = ChronoUnit.DAYS.between(LocalDate.now(), tempDate);
            System.out.println(num);
            if (num > (record.getComingWeeks() * 7) || num == 0) {
                continue;
            }
            String temp = singleCreateScheduling(record, tempDate);
            if (!StrUtil.isBlank(temp)) {
                result = temp + ";" + result;
            }
        }
        result = "本次共计生成" + count + "个排班;" + result;
        return result;
    }

    /**
     * 生成排班
     *
     * @param record
     * @param visiteDate
     * @return
     */
    private synchronized String singleCreateScheduling(OrdSchedulingTemplate record, LocalDate visiteDate) {
        Integer week = DateUtil.weekOfYear(DateUtil.date(visiteDate)) % 2;
        if (visiteDate.isAfter(record.getEffectiveDate()) && visiteDate.isBefore(record.getDueDate()) && !visiteDate.isBefore(LocalDate.now())) {
            OrdScheduling scheduling = schedulingObject(record);
            scheduling.setSchedulingTime(visiteDate);
            //判断有无排班
            Map<String, Object> schedulingMap = new HashMap<String, Object>(8);
            schedulingMap.put("templateId", record.getId());
            schedulingMap.put("schedulingTime", scheduling.getSchedulingTime());
            schedulingMap.put("hospitalId", scheduling.getHospitalId());
            schedulingMap.put("timeState", scheduling.getTimeState());
            List<OrdScheduling> schedulingList = ordSchedulingMapper.selectList(schedulingMap);
            if (CollectionUtil.isEmpty(schedulingList)) {
                // 单双周停诊
                if (record.getFortnightly().equals("0")) {
                    if (!week.equals(0)) {
                        scheduling.setStatus("1");
                        scheduling.setStopServiceReason("医生因私停诊");
                    }
                } else if (record.getFortnightly().equals("1")) {
                    if (!week.equals(1)) {
                        scheduling.setStatus("1");
                        scheduling.setStopServiceReason("医生因私停诊");
                    }
                }
                ordSchedulingMapper.insert(scheduling);
                List<OrdSourceDetail> sourceDetailList = sourceDetailObject(scheduling);
                for (OrdSourceDetail sourceDetail : sourceDetailList) {
                    ordSourceDetailMapper.insert(sourceDetail);
                }
                //设置过期时间
                Duration duration = Duration.between(LocalDateTime.now(), scheduling.getSchedulingTime().atTime(23, 59, 59));
                String sourceDetailKey = "sourceDetail:" + scheduling.getDoctorId() + ":" + scheduling.getId();
                String schedulingKey = "scheduling:" + scheduling.getDoctorId() + ":" + scheduling.getId();
                if (scheduling.getStatus().equals("0")){
                    redisCacheTemplate.opsForValue().set(schedulingKey, scheduling.getAmount(), duration);
                    sourceDetailList.forEach(ordSourceDetail -> {
                        redisCacheTemplate.opsForSet().add(sourceDetailKey, ordSourceDetail.getId());
                    });
                    redisCacheTemplate.expire(sourceDetailKey, duration);
                }
                count++;
                int weeks = visiteDate.getDayOfWeek().getValue() + 1 > 7 ? 1 : visiteDate.getDayOfWeek().getValue() + 1;

                return record.getDepName() + record.getDoctorName() + "的" + LocalDateTimeUtil.format(visiteDate, DatePattern.CHINESE_DATE_PATTERN) + Week.of(weeks).toChinese() + (scheduling.getTimeState().equals(1) ? "上午" : scheduling.getTimeState().equals(2) ? "下午" : "夜门诊") + "的排班生成成功！";
            } else {
                return record.getDepName() + record.getDoctorName() + "的" + LocalDateTimeUtil.format(visiteDate, DatePattern.CHINESE_DATE_PATTERN) + (scheduling.getTimeState().equals(1) ? "上午" : scheduling.getTimeState().equals(2) ? "下午" : "夜门诊") + "的排班已存在，不能重复生成排班！";
            }
        }
        return "";
    }

    /**
     * 定时任务生成排班 默认两周排班
     *
     * @return
     * @throws Exception
     */
    @Transactional(isolation = Isolation.SERIALIZABLE)
    @Scheduled(cron = "0 5 2 ? * *")
    @Override
    public synchronized String createSchedulingBatch() throws Exception {
        Map<String, Object> map = new HashMap<String, Object>(8);
        /**从设置的系统参数中查询设置了多少周*/
        map.put("status", "0");
        List<OrdSchedulingTemplate> schedulingTemplateList = ordSchedulingTemplateMapper.selectList(map);
        String result = "";
        count = 0;
        for (OrdSchedulingTemplate st : schedulingTemplateList) {
            LocalDate visiteDate = getVisiteDate(st);
            for (int i = 0; i <= st.getComingWeeks(); i++) {
                LocalDate tempDate = visiteDate.plusWeeks(i);
                long num = ChronoUnit.DAYS.between(LocalDate.now(), tempDate);
                System.out.println(num);
                if (num > (st.getComingWeeks() * 7) || num == 0) {
                    continue;
                }
                String temp = singleCreateScheduling(st, tempDate);
                if (!StrUtil.isBlank(temp)) {
                    result = temp + ";" + result;
                }
            }
        }
        result = "本次共计生成成功" + count + "个排班;" + result;
        return result;
    }

    /**
     * 定时任务生成排班 默认两周排班
     *
     * @param doctorId
     * @return
     * @throws Exception
     */
    @Transactional(isolation = Isolation.SERIALIZABLE)
    @Override
    public synchronized String createSchedulingBatch(Long doctorId) throws Exception {
        Map<String, Object> map = new HashMap<String, Object>(8);
        /**从设置的系统参数中查询设置了多少周*/
        map.put("status", "0");
        map.put("doctorId", doctorId);
        List<OrdSchedulingTemplate> schedulingTemplateList = ordSchedulingTemplateMapper.selectList(map);
        String result = "";
        count = 0;
        for (OrdSchedulingTemplate st : schedulingTemplateList) {
            LocalDate visiteDate = getVisiteDate(st);
            for (int i = 0; i <= st.getComingWeeks(); i++) {
                LocalDate tempDate = visiteDate.plusWeeks(i);
                long num = ChronoUnit.DAYS.between(LocalDate.now(), tempDate);
                if (num > (st.getComingWeeks() * 7) || num == 0) {
                    continue;
                }
                String temp = singleCreateScheduling(st, tempDate);
                if (!StrUtil.isBlank(temp)) {
                    result = temp + ";" + result;
                }
            }
        }
        result = "本次共计生成成功" + count + "个排班;" + result;
        return result;
    }


    /**
     * 根据排班模板获取排班日期
     *
     * @param record
     * @return
     */
    private LocalDate getVisiteDate(OrdSchedulingTemplate record) {
        //当天一周第几天
        LocalDate.now().getDayOfWeek().getValue();
        int week = LocalDate.now().getDayOfWeek().getValue();
        LocalDate visiteDate = null;
        if (record.getWeek().equals(week)) {
            visiteDate = LocalDate.now();
        } else {
            week = Integer.valueOf(record.getWeek()) - week;
            if (week < 0) {
                week = week + 7;
            }
            visiteDate = LocalDate.now().plusDays(week);
        }
        return visiteDate;
    }

    /**
     * 生成第三方预约号源编码字典
     *
     * @param scheduling
     * @return
     */
    private HashSet<String> generateAppointmentSet(OrdScheduling scheduling) {
        HashSet<String> hashSet = new HashSet<String>(20);
        if (!Optional.ofNullable(scheduling.getAppointmentAmount()).isPresent()) {
            scheduling.setAppointmentAmount(scheduling.getAmount() - scheduling.getAppointmentBegin());
            scheduling.setAmountSurplus(scheduling.getAppointmentAmount());
        }
        if (scheduling.getAppointmentAmount().compareTo(0) > 0) {
            Integer serialNumber = scheduling.getAppointmentBegin();
            for (int i = 0; i < scheduling.getAppointmentAmount(); i++) {
                hashSet.add(serialNumber.toString());
                serialNumber = serialNumber + (scheduling.getIncrease() + 1);
            }
        }
        return hashSet;
    }

    /**
     * 根据模板生成周排
     *
     * @param record
     * @return
     */
    private synchronized OrdScheduling schedulingObject(OrdSchedulingTemplate record) {
        OrdScheduling scheduling = new OrdScheduling();
        scheduling.setHospitalId(record.getHospitalId());
        scheduling.setDepId(record.getDepId());
        scheduling.setDepName(record.getDepName());
        scheduling.setDoctorId(record.getDoctorId());
        scheduling.setDoctorName(record.getDoctorName());
        scheduling.setBinId(record.getBinId());
        scheduling.setBinName(record.getBinName());
        scheduling.setWeek(record.getWeek());

        scheduling.setStartTime(record.getStartTime());
        scheduling.setEndTime(record.getEndTime());
        scheduling.setAmount(record.getAmount());
        scheduling.setAppointmentBegin(record.getAppointmentBegin());
        scheduling.setAppointmentAmount(record.getAppointmentAmount());
        scheduling.setIncrease(record.getIncrease());
        scheduling.setAmountCurrent(1);
        scheduling.setAmountSurplus(record.getAmount());
        scheduling.setClinicAddress(record.getClinicAddress());
        scheduling.setState("0");
        scheduling.setStatus("0");
        scheduling.setAverageVisitTime(record.getAverageVisitTime());
        scheduling.setTemplateId(record.getId());
        scheduling.setRegistrationFee(record.getRegistrationFee());
        scheduling.setTimeState(record.getTimeState());
        scheduling.setTip(record.getTip());
        scheduling.setDoctorPracticeScope(record.getDoctorPracticeScope());
        scheduling.setOriginalSchedule(record.getOriginalSchedule());
        return scheduling;
    }

    /**
     * 根据排班生成号源
     *
     * @param scheduling
     * @return
     */
    private List<OrdSourceDetail> sourceDetailObject(OrdScheduling scheduling) {
        List<OrdSourceDetail> sourceDetailList = new ArrayList<>(80);
        //判断号源序号是否在第三方预约范围之内
        HashSet<String> appointmentSet = generateAppointmentSet(scheduling);
        scheduling.setStartTime(scheduling.getStartTime().plusMinutes(scheduling.getAverageVisitTime() * (-1)));
        for (Integer serialNumber = 1; serialNumber <= scheduling.getAmount(); serialNumber++) {
            OrdSourceDetail sourceDetail = new OrdSourceDetail();
            sourceDetail.setSchedulingId(scheduling.getId());
            sourceDetail.setSchedulingDate(scheduling.getSchedulingTime());

            if (appointmentSet.contains(serialNumber.toString())) {
                sourceDetail.setType("1");
            } else {
                sourceDetail.setType("0");
            }
            sourceDetail.setSchedulingId(scheduling.getId());
            sourceDetail.setVisitTime(scheduling.getStartTime().plusMinutes(scheduling.getAverageVisitTime()));
            scheduling.setStartTime(sourceDetail.getVisitTime());
            sourceDetail.setSchedulingDate(scheduling.getSchedulingTime());
            sourceDetail.setTimeState(scheduling.getTimeState());
            sourceDetail.setSerialNumber(serialNumber.toString());
            sourceDetail.setDepId(scheduling.getDepId());
            sourceDetail.setDepName(scheduling.getDepName());
            sourceDetail.setDoctorId(scheduling.getDoctorId());
            sourceDetail.setDoctorName(scheduling.getDoctorName());
            sourceDetail.setBinId(scheduling.getBinId());
            sourceDetail.setHospitalId(scheduling.getHospitalId());
            sourceDetail.setBinName(scheduling.getBinName());
            sourceDetail.setState(scheduling.getState());
            //号源状态(正常0 未放号或已停诊或者已预约1)
            sourceDetail.setStatus(scheduling.getStatus());
            sourceDetailList.add(sourceDetail);
        }

        return sourceDetailList;
    }


    @Override
    public synchronized String ExtractHisData() throws Exception {
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("status", "0");
        String msg = "";
        List<PubHospital> hospitalList = hospitalMapper.selectList(paramMap);
        for (PubHospital hospital : hospitalList) {
            if (StrUtil.isBlank(hospital.getHosRegionalCode())) {
                continue;
            }
            String tokenStr = "";
            String json = JSONUtil.parseObj("{}").toString();
            try {
                tokenStr = HttpUtil.post(hospital.getHosRegionalCode() + "/outRegplan/select_list", json);
            } catch (Exception e) {
                throw new Exception("调用" + hospital.getHosName() + "中间数据处理服务失败,请确认服务地址：" + hospital.getHosRegionalCode() + "是否正常！");
            }
            String temp = ExtractHisData(tokenStr, hospital);
            if (!StrUtil.isAllBlank(temp)) {
                msg = temp + ";" + msg;
            }
        }
        return msg;
    }


    private String ExtractHisData(String tokenStr, PubHospital hospital) throws Exception {
        String msg = "";
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.clear();
        HttpResult httpResult = JSONUtil.toBean(JSONUtil.parseObj(tokenStr), HttpResult.class);
        List<OutRegPlan> outRegplanList = JSONUtil.toList((JSONArray) httpResult.getData(), OutRegPlan.class);
        paramMap.clear();
        paramMap.put("hospitalId", hospital.getId());
        List<OutRegPlan> regPlanDeleteList = outRegPlanMapper.selectList(paramMap);
        for (OutRegPlan regPlan : outRegplanList) {
            if (!hospital.getId().toString().equals(regPlan.getHospitalId().toString())) {
                throw new Exception("中间服务地址错误，当前机构编码：" + hospital.getId() + " 请确认服务地址是否正确？");
            }
            String redisDepKey = "departments:" + regPlan.getHospitalId() + ":" + regPlan.getKeshibm();
            String redisDocKey = "doctor:" + regPlan.getHospitalId() + ":" + regPlan.getYishengbm();
//            if (!redisCacheTemplate.hasKey(redisDocKey)) {
//                return "第" + regPlan.getSystemid() + "排班记录医生工号为"+regPlan.getYishengbm()+"的医生信息不存在请先更新医生信息";
//            }
//            if (!redisCacheTemplate.hasKey(redisDepKey)) {
//                return "第" + regPlan.getSystemid() + "排班记录科室编码为"+regPlan.getKeshibm()+"科室信息不存在请先更新科室信息";
//            }
            if (regPlan.getSystemid().equals(1200L)) {
                System.out.println(regPlan);
            }
            paramMap.clear();
            paramMap.put("systemid", regPlan.getSystemid());
            paramMap.put("hospitalId", regPlan.getHospitalId());
            List<OutRegPlan> regPlanList = outRegPlanMapper.selectList(paramMap);
            regPlanDeleteList.removeAll(regPlanList);
            //不同步排班数据
            if (!CollectionUtils.isEmpty(regPlanList)) {
                OutRegPlan outRegPlan = regPlanList.get(0);
                if (outRegPlan.getSync().equals("1")) {
                    continue;
                }
            }


            regPlan.setJieshusj(regPlan.getJieshusj().plusMinutes(-5).plusSeconds(-43));
            regPlan.setKaishisj(regPlan.getKaishisj().plusMinutes(-5).plusSeconds(-43));
            //是否已经同步
            if (CollectionUtils.isEmpty(regPlanList)) {
                OrdSchedulingTemplate ordSchedulingTemplate = new OrdSchedulingTemplate();
                ordSchedulingTemplate = createBean(regPlan, ordSchedulingTemplate);
                regPlan.setDoctorName(ordSchedulingTemplate.getDoctorName());
                List<OrdSchedulingTemplate> zzwList = new ArrayList<>();
                zzwList.clear();
                zzwList = createOrdSchedulingTemplateList(regPlan.getKaishisj().toLocalTime(), regPlan.getJieshusj().toLocalTime(), ordSchedulingTemplate);
                List<OrdSchedulingTemplate> ordSchedulingTemplateList = new ArrayList<>(21);
                ordSchedulingTemplateList.clear();
                ordSchedulingTemplateList = createOrdSchedulingTemplateList(regPlan, zzwList);
                for (OrdSchedulingTemplate schedulingTemplate : ordSchedulingTemplateList) {
                    ordSchedulingTemplateMapper.insert(schedulingTemplate);
                }
                regPlan.setSync("0");

                outRegPlanMapper.insert(regPlan);
            } else {
                paramMap.put("originalSchedule", regPlan.getSystemid());
                paramMap.put("hospitalId", regPlan.getHospitalId());
                List<OrdSchedulingTemplate> stDelList = ordSchedulingTemplateMapper.selectList(paramMap);
                OrdSchedulingTemplate ordSchedulingTemplate = new OrdSchedulingTemplate();
                ordSchedulingTemplate = createBean(regPlan, ordSchedulingTemplate);
                regPlan.setDoctorName(ordSchedulingTemplate.getDoctorName());
                List<OrdSchedulingTemplate> zzwList = new ArrayList<>();
                zzwList.clear();
                zzwList = createOrdSchedulingTemplateList(regPlan.getKaishisj().toLocalTime(), regPlan.getJieshusj().toLocalTime(), ordSchedulingTemplate);
                List<OrdSchedulingTemplate> ordSchedulingTemplateList = new ArrayList<>(21);
                ordSchedulingTemplateList.clear();
                ordSchedulingTemplateList = createOrdSchedulingTemplateList(regPlan, zzwList);
                for (OrdSchedulingTemplate schedulingTemplate : ordSchedulingTemplateList) {
                    stDelList.remove(schedulingTemplate);
                    paramMap.clear();
                    paramMap.put("originalSchedule", schedulingTemplate.getOriginalSchedule());
                    paramMap.put("hospitalId", schedulingTemplate.getHospitalId());
                    paramMap.put("week", schedulingTemplate.getWeek());
                    paramMap.put("timeState", schedulingTemplate.getTimeState());
                    List<OrdSchedulingTemplate> ordSchedulingTemplateList1 = ordSchedulingTemplateMapper.selectList(paramMap);
                    if (CollectionUtils.isEmpty(ordSchedulingTemplateList1)) {
                        ordSchedulingTemplateMapper.insert(schedulingTemplate);
                    } else {
                        OrdSchedulingTemplate template = ordSchedulingTemplateList1.get(0);
                        template.setStartTime(schedulingTemplate.getStartTime());
                        template.setEndTime(schedulingTemplate.getEndTime());
                        //主动注销的排班不予以生成
                        if (!template.getStatus().equals("2")) {
                            template.setStatus("0");
                            ordSchedulingTemplateMapper.updateByPrimaryKeySelective(template);
                        }
                    }
                }
                for (OrdSchedulingTemplate st : stDelList) {
                    st.setStatus("1");
                    ordSchedulingTemplateMapper.deleteByPrimaryKey(st.getId());
                }
                outRegPlanMapper.updateByPrimaryKeySelective(regPlan);
            }
        }
        //删除注销排版
        for (OutRegPlan regPlan : regPlanDeleteList) {
            paramMap.clear();
            paramMap.put("originalSchedule", regPlan.getSystemid());
            paramMap.put("hospitalId", regPlan.getHospitalId());
            List<OrdSchedulingTemplate> ordSchedulingTemplateList1 = ordSchedulingTemplateMapper.selectList(paramMap);
            for (OrdSchedulingTemplate ordSchedulingTemplate : ordSchedulingTemplateList1) {
                ordSchedulingTemplate.setStatus("1");
                ordSchedulingTemplateMapper.updateByPrimaryKeySelective(ordSchedulingTemplate);
            }
            paramMap.clear();
            paramMap.put("systemid", regPlan.getSystemid());
            paramMap.put("hospitalId", regPlan.getHospitalId());
            outRegPlanMapper.deleteList(paramMap);
        }
        return "";
    }

    //生成单条模板
    private OrdSchedulingTemplate createBean(OutRegPlan regPlan, OrdSchedulingTemplate schedulingTemplate) throws Exception {
        //his系统排班ID
        schedulingTemplate.setOriginalSchedule(regPlan.getSystemid().toString());
        //排班状态
        schedulingTemplate.setStatus("0");
        //预约号源数
        schedulingTemplate.setAppointmentAmount(0);
        //预约起始号源
        schedulingTemplate.setAppointmentBegin(1);
        //递增间隔
        schedulingTemplate.setIncrease(0);
        //门诊地址
        schedulingTemplate.setClinicAddress("");
        schedulingTemplate.setComingWeeks(1);

        String redisKey = "departments:" + regPlan.getHospitalId() + ":" + regPlan.getKeshibm();
        if (redisCacheTemplate.hasKey(redisKey)) {
            PubDepartments departments = (PubDepartments) redisCacheTemplate.opsForValue().get(redisKey);
            schedulingTemplate.setDepId(departments.getId());
            schedulingTemplate.setDepName(departments.getDepName());
            schedulingTemplate.setHospitalId(departments.getHospitalId());
        } else {
            throw new Exception(regPlan.toString() + "科室信息不存在");
        }


        redisKey = "doctor:" + regPlan.getHospitalId() + ":" + regPlan.getYishengbm();
        if (redisCacheTemplate.hasKey(redisKey)) {
            PubDoctor doctor = (PubDoctor) redisCacheTemplate.opsForValue().get(redisKey);
            schedulingTemplate.setDoctorId(doctor.getId());
            schedulingTemplate.setDoctorName(doctor.getDoctorName());
        } else {
            throw new Exception(regPlan.toString() + "医生信息不存在");
        }
        if (Optional.ofNullable(regPlan.getXianzhisl()).isPresent()) {
            if (regPlan.getXianzhisl().equals(0) || regPlan.getXianzhisl() > 99) {
                regPlan.setXianzhisl(80);
            }
        } else {
            regPlan.setXianzhisl(80);
        }
        if (!Optional.ofNullable(schedulingTemplate.getAmount()).isPresent()) {
            schedulingTemplate.setAmount(regPlan.getXianzhisl());
        }

        //排班有效期
        schedulingTemplate.setEffectiveDate(LocalDate.now());
        schedulingTemplate.setDueDate(LocalDate.now().plusYears(10));

        //设置挂号类型
        HashMap<String, Object> paramMap = new HashMap<>();
        double fee = regPlan.getGuahaofei() + regPlan.getZhenliaofei();
        paramMap.put("fee", regPlan.getGuahaofei() + regPlan.getZhenliaofei());
        List<PubBindInfo> bindInfos = bindInfoMapper.selectList(paramMap);
        PubBindInfo pubBindInfo = new PubBindInfo();
        if (CollectionUtils.isEmpty(bindInfos)) {
            pubBindInfo.setBinName("特需" + fee);
            pubBindInfo.setFee(fee);
            pubBindInfo.setBinType(2);
            pubBindInfo.setStatus("0");
            pubBindInfo.setZlf(regPlan.getZhenliaofei());
            pubBindInfo.setGhf(regPlan.getGuahaofei());
            bindInfoMapper.insert(pubBindInfo);
        } else {
            pubBindInfo = bindInfos.get(0);
            pubBindInfo.setZlf(regPlan.getZhenliaofei());
            pubBindInfo.setGhf(regPlan.getGuahaofei());
            bindInfoMapper.updateByPrimaryKeySelective(pubBindInfo);
        }
        schedulingTemplate.setBinId(pubBindInfo.getId());
        schedulingTemplate.setBinName(pubBindInfo.getBinName());
        schedulingTemplate.setFortnightly("2");
        schedulingTemplate.setRegistrationFee("0");
        schedulingTemplate.setTip("取号时间上午10点下午3点");
        schedulingTemplate.setHospitalId(Long.valueOf(regPlan.getHospitalId()));
        schedulingTemplate.setSync("0");
        schedulingTemplate.setDoctorPracticeScope("1");

        return schedulingTemplate;
    }

    /**
     * 根据排班时间拆分早中晚排班记录
     *
     * @param startTime
     * @param endTime
     * @param st
     * @return
     */
    private List<OrdSchedulingTemplate> createOrdSchedulingTemplateList(LocalTime startTime, LocalTime endTime, OrdSchedulingTemplate st) {
        List<OrdSchedulingTemplate> ordSchedulingTemplateList = new ArrayList<>();
        ordSchedulingTemplateList.clear();
        System.out.println(startTime.compareTo(LocalTime.NOON));
        OrdSchedulingTemplate ordSchedulingTemplate = new OrdSchedulingTemplate();
        if (startTime.compareTo(LocalTime.NOON) <= 0 && endTime.compareTo(LocalTime.NOON) <= 0) {
            //上午排班
            ordSchedulingTemplate = new OrdSchedulingTemplate();
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(startTime);
            ordSchedulingTemplate.setEndTime(endTime);
            Duration duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            Integer average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            ordSchedulingTemplate.setAverageVisitTime(1);
            ordSchedulingTemplate.setTimeState(1);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
        } else if (startTime.compareTo(LocalTime.NOON) >= 0 && endTime.compareTo(LocalTime.of(17, 0, 0)) <= 0) {
            //中午
            ordSchedulingTemplate = new OrdSchedulingTemplate();
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(startTime);
            ordSchedulingTemplate.setEndTime(endTime);
            Duration duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            Integer average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            ordSchedulingTemplate.setTimeState(2);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
        } else if (startTime.compareTo(LocalTime.of(17, 0, 0)) >= 0) {
            //夜门诊
            ordSchedulingTemplate = new OrdSchedulingTemplate();
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(startTime);
            ordSchedulingTemplate.setEndTime(endTime);
            Duration duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            Integer average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            ordSchedulingTemplate.setTimeState(3);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
        } else if (startTime.compareTo(LocalTime.NOON) <= 0 && endTime.compareTo(LocalTime.of(17, 0, 0)) <= 0) {
            //上下午
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(startTime);
            ordSchedulingTemplate.setEndTime(LocalTime.NOON.plusMinutes(-30));
            Duration duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            Integer average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            ordSchedulingTemplate.setTimeState(1);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }

            ordSchedulingTemplate = new OrdSchedulingTemplate();
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(LocalTime.NOON.plusHours(1));
            ordSchedulingTemplate.setEndTime(endTime);
            duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            ordSchedulingTemplate.setTimeState(2);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
        } else if (startTime.compareTo(LocalTime.NOON) >= 0 && endTime.compareTo(LocalTime.of(17, 0, 0)) >= 0) {
            //下午 夜门诊
            ordSchedulingTemplate = new OrdSchedulingTemplate();
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(startTime);
            ordSchedulingTemplate.setEndTime(LocalTime.of(17, 0, 0));
            ordSchedulingTemplate.setTimeState(2);
            Duration duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            Integer average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }

            ordSchedulingTemplate = new OrdSchedulingTemplate();
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(LocalTime.of(18, 0, 0));
            ordSchedulingTemplate.setEndTime(endTime);
            ordSchedulingTemplate.setTimeState(3);
            duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
        } else if (startTime.compareTo(LocalTime.NOON) <= 0 && endTime.compareTo(LocalTime.of(17, 0, 0)) >= 0) {
            //早中晚
            ordSchedulingTemplate = new OrdSchedulingTemplate();
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(startTime);
            ordSchedulingTemplate.setEndTime(LocalTime.NOON.plusMinutes(-30));
            ordSchedulingTemplate.setTimeState(1);
            Duration duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            Integer average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }


            ordSchedulingTemplate = new OrdSchedulingTemplate();
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(LocalTime.NOON.plusHours(1));
            ordSchedulingTemplate.setEndTime(LocalTime.of(17, 0, 0));
            ordSchedulingTemplate.setTimeState(2);
            duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }

            ordSchedulingTemplate = new OrdSchedulingTemplate();
            BeanUtil.copyProperties(st, ordSchedulingTemplate);
            ordSchedulingTemplate.setStartTime(LocalTime.of(18, 0, 0));
            ordSchedulingTemplate.setEndTime(endTime);
            ordSchedulingTemplate.setTimeState(3);
            duration = Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime());
            average = (int) (Math.floor(duration.getSeconds() / (60 * ordSchedulingTemplate.getAmount())));
            ordSchedulingTemplate.setAverageVisitTime(average);
            if (Duration.between(ordSchedulingTemplate.getStartTime(), ordSchedulingTemplate.getEndTime()).getSeconds() > 3600) {
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
        }
        return ordSchedulingTemplateList;
    }

    /**
     * 根据排班日期拆分排班记录
     *
     * @param regplan
     * @param schedulingTemplates
     * @return
     */
    private List<OrdSchedulingTemplate> createOrdSchedulingTemplateList(OutRegPlan regplan, List<OrdSchedulingTemplate> schedulingTemplates) {
        List<OrdSchedulingTemplate> ordSchedulingTemplateList = new ArrayList<>();
        ordSchedulingTemplateList.clear();
        OrdSchedulingTemplate ordSchedulingTemplate = new OrdSchedulingTemplate();
        for (OrdSchedulingTemplate st : schedulingTemplates) {
            if (regplan.getRiqi1() != null && regplan.getRiqi1().equals("√")) {
                ordSchedulingTemplate = new OrdSchedulingTemplate();
                BeanUtil.copyProperties(st, ordSchedulingTemplate);
                ordSchedulingTemplate.setWeek(1);
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
            if (regplan.getRiqi2() != null && regplan.getRiqi2().equals("√")) {
                ordSchedulingTemplate = new OrdSchedulingTemplate();
                BeanUtil.copyProperties(st, ordSchedulingTemplate);
                ordSchedulingTemplate.setWeek(2);
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
            if (regplan.getRiqi3() != null && regplan.getRiqi3().equals("√")) {
                ordSchedulingTemplate = new OrdSchedulingTemplate();
                BeanUtil.copyProperties(st, ordSchedulingTemplate);
                ordSchedulingTemplate.setWeek(3);
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
            if (regplan.getRiqi4() != null && regplan.getRiqi4().equals("√")) {
                ordSchedulingTemplate = new OrdSchedulingTemplate();
                BeanUtil.copyProperties(st, ordSchedulingTemplate);
                ordSchedulingTemplate.setWeek(4);
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
            if (regplan.getRiqi5() != null && regplan.getRiqi5().equals("√")) {
                ordSchedulingTemplate = new OrdSchedulingTemplate();
                BeanUtil.copyProperties(st, ordSchedulingTemplate);
                ordSchedulingTemplate.setWeek(5);
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
            if (regplan.getRiqi6() != null && regplan.getRiqi6().trim().equals("√")) {
                ordSchedulingTemplate = new OrdSchedulingTemplate();
                BeanUtil.copyProperties(st, ordSchedulingTemplate);
                ordSchedulingTemplate.setWeek(6);
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
            if (regplan.getRiqi7() != null && regplan.getRiqi7().equals("√")) {
                ordSchedulingTemplate = new OrdSchedulingTemplate();
                BeanUtil.copyProperties(st, ordSchedulingTemplate);
                ordSchedulingTemplate.setWeek(7);
                ordSchedulingTemplateList.add(ordSchedulingTemplate);
            }
        }
        return ordSchedulingTemplateList;
    }

}
